import { process } from 'gremlin';

import { FlowStep } from '~/core/dsl';
import { Configuration } from '~/core/Configuration/index';

export abstract class TraverseStrategy {
    abstract getNeighbors(id: number): Promise<FlowStep[]>;
}

export class BaseTraverse extends TraverseStrategy {
    private getContext = Configuration.getContextCallback();
    async getNeighbors(id: number, fgname: string = 'dfg'): Promise<FlowStep[]> {
        const steps: FlowStep[] = [];
        const results = await Configuration.dbContext.gremlin.source.V(id)
            .inE(fgname)
            .dedup()
            .project('e', 'v')
            .by()
            .by(process.statics.outV())
            .toList()
        results.forEach((result: Map<string, any>) => {
            const value = this.getContext().getValue(result.get('v'));
            const edge = result.get('e');
            steps.push([value, edge]);
        });
        return steps;
    }
}

export class DfgTraverse extends BaseTraverse {
    async getNeighbors(id: number): Promise<FlowStep[]> {
        return await super.getNeighbors(id, 'dfg')
    }
}

export class CfgTraverse extends BaseTraverse {
    async getNeighbors(id: number): Promise<FlowStep[]> {
        return await super.getNeighbors(id, 'cfg')
    }
}
